package com.dlc.felear.xiaoensale.deviceControlSf;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.helper.JsonHelper;
import com.dlc.felear.xiaoensale.helper.Session;

import org.simple.eventbus.EventBus;

import java.util.HashMap;
import java.util.concurrent.ThreadPoolExecutor;

public class GuotiActionControl implements Handler.Callback {
    private static final String TAG = "GuotiActionControl";
    private static final int WHAT_TIMEOUT = 21121;
    public static final int MIN_IO = 14;
    public static final int MAX_IO = 20;
    public static final int XWIO = 16;
    /**
     * 菜出锅/倒水位置
     */
    public static final int POSITION_1 = 1;
    private JiaobanControl jiaobanControl;
    private Session session;
    private static GuotiActionControl instance;
    /**
     * 炒菜角度 2 3 4 5
     */
    public static final int POSITION_2 = 2;
    public static final int POSITION_3 = 3;
    public static final int POSITION_4 = 4;
    public static final int POSITION_5 = 5;
    public static final int POSITION_6 = 6;
    public static final int POSITION_YD = POSITION_6;
    private int prePosition = 2;
    private int position = POSITION_6;
    private int ccLevel = POSITION_4;
    private boolean ccFlag = false;
    private MotorDiverControl motorDiverControl;
    private boolean position_flag1;
    private boolean position_flag2;
    private boolean position_flag3;
    private boolean position_flag4;
    private boolean position_flag5;
    private boolean position_flag6;
    private int runTimeOut = 10 * 1000;
    private SensorStatusInfo sensorStatusInfo;
    private HashMap<Integer, Integer> gtHashmap = new HashMap<>();
    private boolean isNoDingwei = false;
    private Handler handler;

    public int getCcLevelPosition() {
        return ccLevel;
    }


    private GuotiActionControl(SensorStatusInfo sensorStatusInfo, String serialNum, ThreadPoolExecutor scheduledThreadPool) {
        session = Session.getSession();
        this.sensorStatusInfo = sensorStatusInfo;
        jiaobanControl = new JiaobanControl(serialNum, scheduledThreadPool);
        motorDiverControl = new MotorDiverControl(2, serialNum);
        handler = new Handler(this);
        delayInit(scheduledThreadPool);

    }

    private void delayInit(ThreadPoolExecutor scheduledThreadPool){
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    position = sensorStatusInfo.getIoStatus(16,20);
                    if(position==-1){
                        position=session.getInt(TAG, POSITION_6);
                    }
                    log("上电锅体位置:" + position, 0);
                }catch (Exception e){
                }
            }
        });
    }

    public void setSensorStatusInfo(SensorStatusInfo sensorStatusInfo) {
        jiaobanControl.setSensorStatusInfo(sensorStatusInfo);
    }

    private void resetAllBoolean() {
        position_flag1 = false;
        position_flag2 = false;
        position_flag3 = false;
        position_flag4 = false;
        position_flag5 = false;
        position_flag6 = false;
    }

    private boolean isHasPotion() {
        isNoDingwei = false;
        for (int i = MIN_IO + 1; i <= MAX_IO; i++) {
            if (sensorStatusInfo.getIoStatus(i) == 1) {
                isNoDingwei = true;
                break;
            }
        }
        return isNoDingwei;
    }

    private void handleGtAction(int position) {
        //POSITION_1 最底部的位置 POSITION_6 最上面的位置
       try {
//           log("handleGtAction position="+position,0);
           if (isHasPotion()) {
//               Log.e(TAG, "该时刻在检测点位置:" + position + "当前位置:" + JsonHelper.toJson(sensorStatusInfo.getLlStatus()));
               runAction(position);
           } else {
               Log.e(TAG, "该时刻不在检测点位置:" + position + "当前位置:" + JsonHelper.toJson(sensorStatusInfo.getLlStatus()));
               isNoDingwei = false;
               startRun(Constant.M_DIR_FZ, getRunTimeout(position));
               saveGtActions(position);
           }
       }catch (Exception e){
           log("handleGtAction Exception="+e.getMessage(),0);
       }
    }

    public void runAction(int position) {
        //POSITION_1 最底部的位置 POSITION_6 最上面的位置  锅朝下运动，正转  锅朝上运动 反转
        initCurPosition();
        gtHashmap.clear();
        isNoDingwei = false;
        log("runAction 将要转到的：position：" + position + " lsatPrePosition：" + prePosition, 0);
        if (position == POSITION_1) {//出菜 倒水炒菜角度
            log("runAction 出菜 倒水位置", 0);
            if (sensorStatusInfo.getIoStatus(position + MIN_IO) != 1) {
                prePosition = position;
                jiaobanControl.cgJiaoban();
                startRun(Constant.M_DIR_ZZ, getRunTimeout(position));
            } else {
                log("锅已是倒菜状态", 1);
            }
        }
        else if (position == POSITION_2 || position == POSITION_3 || position == POSITION_4 || position == POSITION_5) {//炒菜位置角度
//            log("runAction 炒菜角度:"+ccLevel, 0);
            prePosition = ccLevel;
            setCcPosition(prePosition);
            runPositionCc(prePosition);
        } else if (position == POSITION_YD) {//加食材
            log("runAction 加食材位置", 0);
            if (sensorStatusInfo.getIoStatus(position + MIN_IO) == 1) {
                log("锅已是复位状态", 1);
            } else {
                resetAllBoolean();
                prePosition = POSITION_YD;
                setCcPosition(prePosition);
                startRun(Constant.M_DIR_FZ, getRunTimeout(POSITION_YD));
            }
        }
    }

    private void setCcPosition(int ccLevel) {
        resetAllBoolean();
        switch (ccLevel) {
            case 1:
                position_flag1 = true;
                break;
            case 2:
                position_flag2 = true;
                break;
            case 3:
                position_flag3 = true;
                break;
            case 4:
                position_flag4 = true;
                break;
            case 5:
                position_flag5 = true;
                break;
            case 6:
                position_flag6 = true;
                break;
        }
    }


    public static GuotiActionControl getInstance(SensorStatusInfo sensorStatusInfo, String serialNum, ThreadPoolExecutor scheduledThreadPool) {
        if (instance == null) {
            synchronized (GuotiActionControl.class) {
                if (instance == null) {
                    instance = new GuotiActionControl(sensorStatusInfo,serialNum, scheduledThreadPool);
                }
            }
        }
        return instance;
    }

    private void saveGtActions(int position) {
        gtHashmap.put(position, position);
    }


    /**
     * 锅体旋转搅拌
     *
     * @param level 锅体转速档位
     */
    public void gtJb(int level, int dir) {
        log("搅拌:" + level + " dir=" + dir, 0);
        jiaobanControl.jiaobanAction(dir, level);
    }

    /**
     * 初始化超时时长
     *
     * @param prePosition
     * @return
     */
    private int getRunTimeout(int prePosition) {
        int temp = runTimeOut;
        if (Math.abs(position - prePosition) <= 1) {
            temp = 4 * 1000;
        }
        if (Math.abs(position - prePosition) <= 2 && Math.abs(position - prePosition) > 1) {
            temp = 6 * 1000;
        }
        if (Math.abs(position - prePosition) <= 3 && Math.abs(position - prePosition) > 2) {
            temp = 8 * 1000;
        }
        if (Math.abs(position - prePosition) <= 4 && Math.abs(position - prePosition) > 3) {
            temp = 10 * 1000;
        }
        if (Math.abs(position - prePosition) <= 5 && Math.abs(position - prePosition) > 4) {
            temp = 13 * 1000;
        }
//        log("转动超时停止时间:" + runTimeOut, 0);
        return temp;
    }


    /**
     * 复位
     */
    public void fuWei() {
        log("复位操作",0);
        runPositionJsc();
    }

    /**
     * 接受洗锅指令
     */
    public void actionXg() {
        SDJCposition();
    }


    /**
     * @param num
     */
    public void sensorStatus(int num) {
//        log("num=" + num, 0);
        if (num < MIN_IO || num > MAX_IO) {
            return;
        }
        num = num - MIN_IO;
        log("重置后的 num=" + num, 0);
        recordPosition(num);
//        if (isNoDingwei && !gtHashmap.isEmpty()) {
//            handlerGtCache();
//            return;
//        }
        switch (num) {
            case POSITION_6://加食材感应位置
                stop();
                break;
            case POSITION_2://炒菜位应位置
            case POSITION_3:
            case POSITION_4:
            case POSITION_5:
                stopCcPosition(num);
                break;
            case POSITION_1:
                stop();
                break;
        }
    }

    /**
     * 存储指令
     */
    private void handlerGtCache() {
        log("handlerGtCache gtHashmap;" + JsonHelper.toJson(gtHashmap), 0);
        isNoDingwei = false;
        for (Integer position : gtHashmap.keySet()) {
            runAction(position);
        }
    }

    /**
     * 炒菜角度触发处理逻辑
     *
     * @param position
     */
    private void stopCcPosition(int position) {
        log("stopCcPosition position=" + position + " ccLevel=" +
                ccLevel + " position_flag3=" + position_flag3 + " position_flag4=" + position_flag4 + " position_flag5=" + position_flag5 + " ccFlag=" + ccFlag, 0);
        //转到炒菜角度
        if ((position == POSITION_2&&position_flag2)||(position == POSITION_3&&position_flag3)||
                (position == POSITION_4&&position_flag4)||(position == POSITION_5&&position_flag5)) {
            stop();
        }
        //出锅逻辑
        if (!ccFlag && position_flag1 && position == POSITION_2) {
            log("出锅逻辑",0);
            motorDiverControl.setSpeed(7);
            startRun(Constant.M_DIR_ZZ, 7000);
        }
        //复位逻辑
        if (!ccFlag && position_flag6 && position == POSITION_2) {
            log("复位逻辑",0);
            startRun(Constant.M_DIR_FZ, 5000);
        }
    }

    /**
     * 判断锅体是否在原位
     *
     * @return
     */
    public boolean gtIsYw() {
        return sensorStatusInfo.getIoStatus(MAX_IO) == 1;
    }


    /**
     * 获取锅体位置
     *
     * @return
     */
    public int getPositon() {
        initCurPosition();
        log("getPositon=" + 0 + " p=" + position, 0);
        return this.position;
    }

    /**
     * 转到炒菜位置
     */
    public void runPositionJsc() {
       try {
           initCurPosition();
           resetAllBoolean();
           handleGtAction(POSITION_6);
       }catch (Exception e){
          log("runPositionJsc Exception:"+e.getMessage(),0);
       }
    }

    /**
     * 转到炒菜位置
     */
    public void runPositionCc(int prePosition) {
        initCurPosition();
        //判断转动方向
        log("判断炒菜位置 runPositionCc prePosition=" + prePosition + " position=" + position + " ccLevel=" + ccLevel, 0);
        if (prePosition == position) {
            log("已经在炒菜位置了", 0);
            return;
        }
//        setCcPosition(prePosition);
        if (prePosition > position) {
            startRun(Constant.M_DIR_FZ, getRunTimeout(prePosition));
        } else {
            startRun(Constant.M_DIR_ZZ, getRunTimeout(prePosition));
        }
    }


    /**
     * 出锅
     */
    public void actionCg() {
        resetAllBoolean();
        position_flag1 = true;
        handleGtAction(POSITION_1);
    }

    public void setCcLevel(int num, int delay) {
//        log("炒菜指令:" + num, 0);
        resetAllBoolean();
        if (num > 0 && num < 5) {
            if (num == 1) {
                position_flag2 = true;
            } else if (num == 2) {
                position_flag3 = true;
            } else if (num == 3) {
                position_flag4 = true;
            } else if (num == 4) {
                position_flag5 = true;
            }
            ccLevel = num+1;
            log("炒菜角度:"+num+" 将要转到位置:" + ccLevel + " 锅体当前位置:" + position, 0);
            if (ccLevel == position ) {
                log("已经在炒菜位置了", 0);
                return;
            }
            if (ccLevel < POSITION_2) {
                log("已经在最低位置了", 0);
                return;
            }
            handleGtAction(ccLevel);
        }
    }

    private void initCurPosition() {
        int temp = sensorStatusInfo.getIoStatus(MIN_IO, MAX_IO) - MIN_IO;
//        Log.e(TAG, "initCurPosition temp=" + temp + " position:" + (temp - MIN_IO));
        if (temp != -1 && temp > 0 && temp < 7) {
            position = temp;
        }
    }

    /**
     * 获取炒菜角度
     *
     * @return
     */
    public int getCcLevel() {
        if (ccLevel > 5 || ccLevel < 3) {
            return POSITION_3;
        }
        return ccLevel;
    }

    /**
     * 开始转动
     *
     * @param dir
     * @param timeOut
     */
    private void startRun(int dir, int timeOut) {
        log("锅体转动方向：" + dir + " timeOut=" + timeOut + " position=" + position, 0);
        if (ccFlag && position == POSITION_2 && dir == Constant.M_DIR_ZZ) {
            log("炒菜期间不能向下转动", 0);
            return;
        }
        if (position == POSITION_1 && dir == Constant.M_DIR_ZZ) {
            log("不能再向下转动", 0);
            return;
        }
        if (position == POSITION_6 && dir == Constant.M_DIR_FZ) {
            log("不能再向前转动", 0);
            return;
        }
        handler.removeMessages(WHAT_TIMEOUT);
        handler.sendEmptyMessageDelayed(WHAT_TIMEOUT, timeOut);
        motorDiverControl.setAlwaysRun(dir);
    }

    /**
     * 手动加菜位置
     */
    public void SDJCposition() {
        resetAllBoolean();
        position_flag3=true;
        ccFlag = false;
        handleGtAction(POSITION_3);
    }


    /**
     * 信息显示
     *
     * @param msg
     */
    private void log(String msg, int flag) {
        Log.e(TAG, msg);
        if (flag == 1) {
            EventBus.getDefault().post(msg, Constant.DEVICE_STATUS_MSG_SHOW);
        }
    }

    /**
     * @param flag f炒菜结束 t炒菜开始
     */
    public void isChaocaiStatus(boolean flag) {
        if (!flag) {
            ccLevel = POSITION_4;
        }
        ccFlag = flag;
    }

    private void recordPosition(int num) {
        if (num < 7 && num > 0) {
            position = num;
            session.setInt(TAG, num);
        }
    }

    public void allStop() {
        motorDiverControl.stop(1);
        jiaobanControl.allStop();
    }


    public String getErrorMsg() {
        if (sensorStatusInfo.getIoStatus(XWIO) == 1) {
            return "锅体超出限位，请联系管理人员";
        }
        if (!gtIsYw()) {
            return "锅体未复位，请手动复位";
        }
        return "";
    }


    public void setDaoshuiAction() {
        actionCg();
    }


    /**
     * 正反转切换
     *
     * @param sec
     */
    public void controlZfRun(int sec) {
//        log("切换正反转:msec=" + sec, 0);
//        jiaobanControl.controlZfRun(sec);
    }

    private void stop() {
        log("stop", 0);
        handler.removeMessages(WHAT_TIMEOUT);
        motorDiverControl.stop(1);
        motorDiverControl.setSpeed(Constant.GT_DEFAULT_SPEED);
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == WHAT_TIMEOUT) {
            stop();
        }
        return false;
    }

    public void setSpeed(int gtDefaultSpeed) {
        motorDiverControl.setSpeed(gtDefaultSpeed);
    }

    public boolean checkYttlP() {
        return true;
    }
}
